using System.Net.Sockets;
using System;
using System.Threading.Tasks;
using foundation.events;
using foundation.socket;
using foundation.structure;
using foundation;
using System.Runtime.CompilerServices;

namespace mao
{

    internal static class MaoSocket
    {
        public static WebSocket websocket = new WebSocket();
        public static AsyncTokenTask GetAwaiter(this AsyncTokenTask self)
        {
            return self;
        }

        // public static MaoSocket socket = new MaoSocket();

        public async static Task<object> asyncToken(ushort code, object value = null)
        {
            var tokenTask = ClassUtils.PoolGet<AsyncTokenTask>();
            tokenTask.request(websocket, 6, code, value);
            var data = await tokenTask;
            ClassUtils.PoolSet(tokenTask);
            return data;
        }

        public async static Task<object> login(object value = null)
        {
            var tokenTask = ClassUtils.PoolGet<AsyncTokenTask>();
            tokenTask.request(websocket, 100, 100, value);
            var data = await tokenTask;
            ClassUtils.PoolSet(tokenTask);
            return data;
        }


        // public async static void Connect(string url)
        // {
        //     await websocket.Connect(url);
        // }
    }

    internal class AsyncTokenTask : INotifyCompletion
    {
        static uint token = 0;

        [Recycle(null, true)]
        RequestTokenVO vo = new RequestTokenVO();
        [Recycle(false)]
        bool _IsComplete = false;
        [Recycle(null)]
        object data = null;
        [Recycle(null)]
        Action continuation = null;

        public void request(WebSocket websocket, ushort top, ushort code, object value = null)
        {
            var currentToken = token++;
            vo.code = code;
            vo.value = value;
            vo.token = currentToken;
            Facade.SOCKET.AddEventListener(top, handler);
            websocket.SimpleSend(top, vo);
        }

        void handler(EventX evt)
        {
            evt.CurrentTarget.RemoveEventListener(evt.Type, handler);

            var result = DataConvert.ConvertAMF3Data<RequestTokenVO>(evt.Data);
            // var a = DataConvert.ConvertAMF3Data<RequestTokenVO>(evt.Data, typeof(RequestTokenVO));
            if (result != null && result.token == vo.token)
            {
                data = result.value;
                continuation?.Invoke();
            }
        }


        public object GetResult()
        {
            return data;
        }

        public bool IsCompleted
        {
            get
            {
                return _IsComplete;
            }
        }

        public void OnCompleted(Action continuation)
        {
            this.continuation = continuation;
        }
    }

}